#ifndef _CEXCEPTION_H_
#define _CEXCEPTION_H_
#include <setjmp.h>
#include <stdlib.h>
#include <stdarg.h>
#include <execinfo.h>
#include <stdio.h>
#include <signal.h>
#include <iostream>
#include <string.h>


#define REASONABLE_TIME 10
#define REASONABLE_VOLUNTARY_SWITCH 10
#define REASONABLE_NONVOLUNTARY_SWITCH 10

jmp_buf env;
int try_signal;

void ShowStack()
{
    int i;
    void * buffer[1024];
    int n = backtrace(buffer, 1024);
    char ** symbols = backtrace_symbols(buffer, n);
    for (i = 0; i < n; i++)
    {
        printf("%s\n", symbols[i]);
    }

    int tem_cpsr = 0;
    asm
    (
    "stmfd sp!,{r1}\n"
    "mrs r1,cpsr\n"
    "mov %0,r1\n"
    "ldmfd sp!,{r1}\n"
    :"=r"(tem_cpsr)
    :
    :
    );
    printf("cpsr :: %x\n",tem_cpsr);
}

int check_voluntary_ctxt_switches()
{
    pid_t pid = getpid();
    char proc_status_file_name[30];
    sprintf(proc_status_file_name, "/proc/%d/status", pid);
    printf("%s\n",proc_status_file_name);
    FILE * fp = fopen(proc_status_file_name, "r");
    char name[1024];
    char num[1024];
    int voluntary, nonvoluntary;
    while(1)
    {
        fscanf(fp, "%s\t%s", num, name);
        if( feof(fp) )
        { 
            break ;
        }
        if (!strcmp("voluntary_ctxt_switches:", name))
        {
            printf("get voluntary switches : %s\n", num);
            voluntary = atoi(num);
        }
        if (!strcmp("nonvoluntary_ctxt_switches:", name))
        {
            printf("get nonvoluntary switches : %s\n", num);
            nonvoluntary = atoi(num);

        }
    }
    fclose(fp);

    if (0)// set "error" status
    {
        return 0;
    }
    else
    {
        return 1;
    }
}

void SigSegvProc(int signo)
{
    if (signo == SIGSEGV)
    {
        printf("Receive SIGSEGV signal\n");
    }
    else if (signo == SIGBUS)
    {
        printf("Receive SIGBUS signal\n");
    }
    else if (signo == SIGILL)
    {
        printf("Receive SIGSEGV signal\n");
    }
    else if (signo == SIGALRM)
    {
        printf("Receive SIGALRM signal\n");
        if(check_voluntary_ctxt_switches())
        {
            alarm(REASONABLE_TIME);
            return;
        }
    }
    else
    {
        printf("this is sig %d", signo);
    }
    ShowStack();
    siglongjmp(env,1);
}

void RegSig()
{
    signal(SIGSEGV, SigSegvProc);
    signal(SIGBUS, SigSegvProc);
    signal(SIGILL, SigSegvProc);
    signal(SIGALRM, SigSegvProc);
    alarm(REASONABLE_TIME);
}


#define TRY \
    RegSig(); \
    try_signal = sigsetjmp(env,1); \
    if (try_signal == 0) \
    { \

#define CATCH \
    } \
    else \
    { \
        printf("jump this code !!"); \
    } \
#endif